#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUF_SIZE 30
void error_handling(char *message);
void read_routine(int sock, char *buf);
void write_routine(int sock, char *buf);

void read_childproc(int sig);   // 子进程技术的信号函数

int main(int argc, char *argv[])
{
	if(argc!=3) {
		printf("Usage : %s <IP> <port>\n", argv[0]);
		exit(1);
	}

	int    sock, state;
	pid_t  pid;
	char   buf[BUF_SIZE];
	struct sockaddr_in serv_adr;
	struct sigaction act;

	act.sa_handler = read_childproc;
	act.sa_flags   = 0;
    sigemptyset(&act.sa_mask);
	state     = sigaction(SIGCHLD, &act, 0);  // 注册子进城结束的信号函数
	
	sock = socket(PF_INET, SOCK_STREAM, 0);  
	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family      = AF_INET;
	serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
	serv_adr.sin_port        = htons(atoi(argv[2]));
	
	if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
		error_handling("connect() error!");

	pid=fork();
	if(pid==0)
		write_routine(sock, buf);
	else 
		read_routine(sock, buf);

	close(sock);
	return 0;
}

void read_routine(int sock, char *buf)
{
	while(1)
	{
		int str_len=read(sock, buf, BUF_SIZE);
		if(str_len==0)
			return;

		buf[str_len]=0;
		printf("Message from server: %s", buf);
	}
}
void write_routine(int sock, char *buf)
{
	while(1)
	{
		// fgets 函数用于从指定的文件流中读取一行文本
		// char *fgets(char *str, int n, FILE *stream);
		fgets(buf, BUF_SIZE, stdin);
		if(!strcmp(buf,"q\n") || !strcmp(buf,"Q\n"))
		{	
			shutdown(sock, SHUT_WR);         // 关闭输出流
			return;
		}
		write(sock, buf, strlen(buf));
	}
}
void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

void read_childproc(int sig)
{
	pid_t pid;
	int   status;
    // 子进程结束时系统发起调用的，因此返回的pid一定不为0
	pid = waitpid(-1, &status, WNOHANG);        
	printf("removed proc id: %d \n", pid);
}